package com.wfm.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.Stateless;

import com.common.util.ObjectUtils;
import com.core.exception.ServiceException;
import com.core.exception.UserException;
import com.core.service.AppBaseService;
import com.wfm.entity.TB_WFM_DEF_HANDLES;
import com.wfm.entity.TB_WFM_DEF_NODE;
import com.wfm.entity.TB_WFM_DEF_NODEFORM;
import com.wfm.entity.TB_WFM_DEF_NODE_POSITION;
import com.wfm.entity.TB_WFM_DEF_TRANS;
import com.wfm.entity.TB_WFM_DEF_WORKFLOW;
import com.wfm.entity.TB_WFM_INS_NODE;
import com.wfm.entity.TB_WFM_INS_WORKFLOW;

/**
 * 流程服务
 */
@Stateless
public class SVC_WORKFLOW extends AppBaseService implements SVC_WORKFLOWRemote, SVC_WORKFLOWLocal { 

	@Override
	public Map ADD_DEF_WORKFLOW(Map param) {
		TB_WFM_DEF_WORKFLOW bo = ObjectUtils.mapToJavaBean(param, TB_WFM_DEF_WORKFLOW.class);
		bo.setID(bo.uuid());
		bo.setCREATE_TIME(getOpTime(param));
		bo.setOP_ITEM(getOpTime(param));
		bo.setOPID(getOpid(param));
		getJpaDao().save(bo);
		return ObjectUtils.javaBeanToMap(bo);
	}

	@Override
	public Map UPD_DEF_WORKFLOW(Map param) {
		TB_WFM_DEF_WORKFLOW bo = ObjectUtils.mapToJavaBean(param, TB_WFM_DEF_WORKFLOW.class);
		bo.setOP_ITEM(getOpTime(param));
		bo.setOPID(getOpid(param));
		TB_WFM_DEF_WORKFLOW po = getJpaDao().find(TB_WFM_DEF_WORKFLOW.class, bo.getID());
		ObjectUtils.copyJavaBeanToBean(bo, po, "CREATE_TIME");
		getJpaDao().update(po);
		return ObjectUtils.javaBeanToMap(bo);
	}

	@Override
	public void DEL_DEF_WORKFLOW(Map param) {
		TB_WFM_DEF_WORKFLOW dto = ObjectUtils.mapToJavaBean(param, TB_WFM_DEF_WORKFLOW.class);
		TB_WFM_DEF_WORKFLOW po = getJpaDao().find(TB_WFM_DEF_WORKFLOW.class, dto.getID());

		po.setOP_ITEM(getOpTime(param));
		po.setOPID(getOpid(param));
		po.setSTATUS(TB_WFM_DEF_WORKFLOW.STATUS_DEAD);
		getJpaDao().update(po);
	}

	@Override
	public void SAVE_WORKFLOW_VIEW(Map param) { 
		List list_NODE = (List)param.get("list_NODE");
		List list_LINE = (List)param.get("list_LINE");
		String WFID = (String)param.get("WFID");
		HashMap<String,TB_WFM_DEF_NODE> nodeCatch = new HashMap<String,TB_WFM_DEF_NODE> (); 
		//处理节点
		HashMap<String,TB_WFM_DEF_NODE> tempMap = new HashMap<String,TB_WFM_DEF_NODE> ();
		if(WFID!=null && !WFID.isEmpty()){
		   List<TB_WFM_DEF_NODE> list = (List<TB_WFM_DEF_NODE>) getResultList("select o from TB_WFM_DEF_NODE o where WFID='"+WFID+"'");
		   for(TB_WFM_DEF_NODE n : list){
			   tempMap.put(n.getID(), n);
		   } 
		  
		   List<String> tmpList = (List<String>) getResultList("select DISTINCT HANDLE_ID from TB_WFM_DEF_HANDLES where WFID='"+WFID+"'");
		    for(String id : tmpList){
		        	getServiceInterface().doService("RMServiceBean", "deleteAFuncByWF", id );
		    }
		} 
	        
		for(Object item:list_NODE){
			Map map = (Map)item;
			Map m_NODE = (Map)map.get("NODE");
	        Map m_NODE_POSITION = (Map)map.get("NODE_POSITION");
	        Map m_NODEFORM = (Map)map.get("NODEFORM");
	        List list_TB_WFM_DEF_HANDLES = (List)map.get("list_TB_WFM_DEF_HANDLES");
	        
	        TB_WFM_DEF_NODE o_node= ObjectUtils.mapToJavaBean(m_NODE, TB_WFM_DEF_NODE.class);
	        o_node.setWFID(WFID);
	        nodeCatch.put(o_node.getNAME(), o_node);
	        if( o_node.getID() == null){
	        	 o_node.setID(o_node.uuid());
	        	 getJpaDao().save(o_node);
	        }else{
	        	 getJpaDao().update(o_node);
	        	 tempMap.remove(o_node.getID());
	        }
	        
	        TB_WFM_DEF_NODE_POSITION o_NODE_POSITION= ObjectUtils.mapToJavaBean(m_NODE_POSITION, TB_WFM_DEF_NODE_POSITION.class);
	        o_NODE_POSITION.setNID(o_node.getID());
	        o_NODE_POSITION.setWFID(WFID);
	        if( o_NODE_POSITION.getID() == null){
	        	o_NODE_POSITION.setID(o_NODE_POSITION.uuid());
	        	 getJpaDao().save(o_NODE_POSITION);
	        }else{
	        	 getJpaDao().update(o_NODE_POSITION);
	        }
	        String funcId = null;
	        TB_WFM_DEF_NODEFORM o_NODEFORM= null;
	        if(m_NODEFORM!=null){
	        	o_NODEFORM= ObjectUtils.mapToJavaBean(m_NODEFORM, TB_WFM_DEF_NODEFORM.class);
	        	o_NODEFORM.setNID(o_node.getID());
	        	o_NODEFORM.setWFID(WFID);
	        	if( o_NODEFORM.getID() == null){
	        		o_NODEFORM.setID(o_NODEFORM.uuid());
		        	 getJpaDao().save(o_NODEFORM);
		        }else{
		        	 getJpaDao().update(o_NODEFORM);
		        } 
	        	if("SysFunction".equals(o_NODEFORM.getFORM_TYPE())){
	        		funcId = (String) getServiceInterface().doService("RMServiceBean", "getFuncIdByCode", o_NODEFORM.getFORM_CODE());
	        	}
	       } 
	      
	        if(list_TB_WFM_DEF_HANDLES!=null  ){  
	        	doExecuteUpdate("delete from TB_WFM_DEF_HANDLES where NID='"+o_node.getID()+"'"); 
	            HashMap cacheMap = new HashMap();
	            int i=0;
	        	for(Object o : list_TB_WFM_DEF_HANDLES){
	        		Map m_HANDLES = (Map)o;
	        		TB_WFM_DEF_HANDLES o_HANDLES= ObjectUtils.mapToJavaBean(m_HANDLES, TB_WFM_DEF_HANDLES.class);
	        		if(cacheMap.get(o_HANDLES.getHANDLE_ID())!=null)continue;
	        		int j = (++i); 
	        		cacheMap.put(o_HANDLES.getHANDLE_ID(), o_HANDLES);
	        		o_HANDLES.setNID(o_node.getID()); 
	        		o_HANDLES.setID(o_HANDLES.uuid()); 
	        		o_HANDLES.setWFID(WFID);
	        		getJpaDao().save(o_HANDLES);  
	        	
	        		if(funcId!=null && !funcId.isEmpty()){  
		        		HashMap acl = new HashMap();
		        		acl.put("WHOS_TYPE", o_HANDLES.getHANDLE_TYPE());
		        		acl.put("WHOW_ID", o_HANDLES.getHANDLE_ID());
		        		acl.put("RESOURCE_TYPE", "1");
		        		acl.put("RESOURCE_ID", funcId);
		        		getServiceInterface().doService("RMServiceBean", "addACL", acl);
	        		}else if(o_NODEFORM!=null && "SysFunction".equals(o_NODEFORM.getFORM_TYPE())){
	        			throw new RuntimeException("管理功能表单找不到！");
	        		}
	        	}
	        }  
		}
		for(String key:tempMap.keySet()){
			  TB_WFM_DEF_NODE n = tempMap.get(key);
			  doExecuteUpdate("delete from TB_WFM_DEF_HANDLES where NID='"+n.getID()+"'");
			  doExecuteUpdate("delete from TB_WFM_DEF_NODE_POSITION where NID='"+n.getID()+"'");
			  doExecuteUpdate("delete from TB_WFM_DEF_NODEFORM where NID='"+n.getID()+"'");
			  getJpaDao().delete(TB_WFM_DEF_NODE.class, key);
		}
		
		//处理连接线
		doExecuteUpdate("delete from TB_WFM_DEF_TRANS where WFID='"+WFID+"'");
		for(Object item:list_LINE){
			Map map = (Map)item;
			TB_WFM_DEF_TRANS o_line= ObjectUtils.mapToJavaBean(map, TB_WFM_DEF_TRANS.class);
			TB_WFM_DEF_NODE f_node = nodeCatch.get(o_line.getFROM_NID());
			TB_WFM_DEF_NODE t_node = nodeCatch.get(o_line.getTO_NID());
			
			if(o_line.getNAME()==null){
				o_line.setNAME(t_node.getNAME());
			}
			o_line.setFROM_NID(f_node.getID());
			o_line.setTO_NID(t_node.getID());
			o_line.setWFID(WFID);
			o_line.setID(o_line.uuid());
			o_line.setWFID(WFID);
			
			getJpaDao().save(o_line);  
		}
		
	}

	@Override
	public String DO_START_PROCESS(String wfCode, String opid, Date optime,
			String bo_id, int bo_STATUS, String approveResult,
			String approveMemo) {
		return DO_START_PROCESS(wfCode,null,opid,optime,bo_id,bo_STATUS,approveResult,approveMemo);
	}
	
	private TB_WFM_DEF_NODEFORM getNodeForm(TB_WFM_DEF_NODE node){
		Map param = new HashMap(); 
		param.put("WFID", node.getWFID());
		param.put("NID", node.getID());
		return (TB_WFM_DEF_NODEFORM) querySingleResult("select o from TB_WFM_DEF_NODEFORM  o where o.WFID=:WFID and o.NID=:NID",param);
		 
	}
	private String getHandlerIds(TB_WFM_DEF_NODE node){
		Map param = new HashMap(); 
		param.put("WFID", node.getWFID());
		param.put("NID", node.getID());
		List<String> list= (List<String>) getResultList("select o.HANDLE_ID from TB_WFM_DEF_HANDLES o where o.WFID=:WFID and o.NID=:NID",param);
		 if(list!=null&&list.size()>0){
			 StringBuffer ids = new StringBuffer(); 
			 for(String id:list){
				 ids.append(id).append(",");
			 }
			 return ids.toString();
		 }
		 return null;
	}
	
	/**
	 * 
	 * @param opid          ：操作员ID
	 * @param bo_id         ：业务对象ID
	 * @param bo_STATUS     ：业务对象状态
	 * @param optime        ：操作时间
	 * @param beforeInsNode ：前一环节实例
	 * @param PNID          ：前一环节定义ID
	 * @param CNAME         ：欲启动环节名称,当值为“to_next”时，由系统根据定义决定下一步。
	 * @param accepterIds   ：任务接收人ID
	 * @return
	 * @throws WorkFlowException
	 */
	private List<TB_WFM_INS_NODE> startTask(String opid, String bo_id, int bo_STATUS,Date optime,TB_WFM_INS_NODE beforeInsNode,String PNID,String CNAME, String... accepterIds) throws WorkFlowException{
		if(CNAME==null||CNAME.isEmpty())return null;
        if("to_next".equals(CNAME)){
        	CNAME=null;
		}
		List<TB_WFM_INS_NODE> retTasks = new ArrayList<TB_WFM_INS_NODE>();
		HashMap param=new HashMap();
		param.put("PNID", PNID);
		param.put("CNAME", CNAME); 
		List<TB_WFM_DEF_NODE> def_n_list = (List<TB_WFM_DEF_NODE>) getResultList("Q_WFM_DEF_WORKFLOW.GET_TB_WFM_DEF_NODE_BY_PNID_CNAME",param);
		   
		for(TB_WFM_DEF_NODE def_n_item : def_n_list){ 
			//并行分支
			if("fork".equals(def_n_item.getTYPE())){
				if(CNAME==null){
					CNAME = "to_next";
				}
				retTasks.addAll(startTask(opid,bo_id,bo_STATUS,optime,beforeInsNode,def_n_item.getID(),CNAME,accepterIds));
			}else if("join".equals(def_n_item.getTYPE())){
				int fn_count = queryForResultSize("SELECT COUNT(a_n) FROM TB_WFM_INS_NODE n, TB_WFM_INS_NODE a_n WHERE a_n.END_TIME IS NOT NULL AND n.P_I_NID = a_n.P_I_NID" +
						" AND n.ID='"+beforeInsNode.getID()+"'");
				int dn_count = queryForResultSize("SELECT COUNT(t)FROM TB_WFM_DEF_TRANS t,TB_WFM_DEF_TRANS t1 WHERE t.FROM_NID = t1.FROM_NID" +
						" AND t.TO_NID='"+beforeInsNode.getNID()+"'");
				if(fn_count == dn_count  ){
					retTasks.addAll(startTask(opid,bo_id,bo_STATUS,optime,beforeInsNode,def_n_item.getID(),null,accepterIds));
				} 
			}else if("counter_sign".equals(def_n_item.getTYPE())){
				 if(accepterIds.length==0){
					 throw new RuntimeException("汇签要指定人！");
				 }
				 for(int i=0;i<accepterIds.length;i++ ){ 
					 TB_WFM_INS_NODE ins_n_p = new TB_WFM_INS_NODE();
					 ins_n_p.setID(ins_n_p.uuid()); 
					 ins_n_p.setCREATE_TIME(optime);
					 ins_n_p.setCREATERID(opid); 
					 ins_n_p.setWFID(beforeInsNode.getWFID()); 
					 ins_n_p.setN_SN(beforeInsNode.getN_SN()+1);
					 ins_n_p.setNID(def_n_item.getID());  
					 ins_n_p.setN_NAME(def_n_item.getNAME()); 
					 ins_n_p.setN_CODE(def_n_item.getCODE());
					 ins_n_p.setN_TYPE(def_n_item.getTYPE());
					 TB_WFM_DEF_NODEFORM nForm =  getNodeForm(def_n_item);
					 if(nForm!=null){
						 ins_n_p.setFORM_CODE(nForm.getFORM_CODE());  
						 ins_n_p.setFORM_TYPE(nForm.getFORM_TYPE());
					 } 
					 ins_n_p.setACTOR_ID(accepterIds[i]);
					 ins_n_p.setP_I_NID(beforeInsNode.getID()); 
					 ins_n_p.setBO_ID(bo_id);
					 ins_n_p.setBO_STATUS(bo_STATUS);
					
					 getJpaDao().save(ins_n_p);
					 retTasks.add(ins_n_p);
				 }
			}if("end".equals(def_n_item.getTYPE())){
				throw new WorkFlowException(WorkFlowException.RET_END);
				
			}  else{
				 TB_WFM_INS_NODE ins_n_p = new TB_WFM_INS_NODE();
				 ins_n_p.setID(ins_n_p.uuid()); 
				 ins_n_p.setCREATE_TIME(optime);
				 ins_n_p.setCREATERID(opid); 
				 ins_n_p.setWFID(beforeInsNode.getWFID()); 
				 ins_n_p.setN_SN(beforeInsNode.getN_SN()+1);
				 ins_n_p.setNID(def_n_item.getID());
				 ins_n_p.setN_NAME(def_n_item.getNAME()); 
				 ins_n_p.setN_CODE(def_n_item.getCODE());
				 ins_n_p.setN_TYPE(def_n_item.getTYPE());
				 TB_WFM_DEF_NODEFORM nForm =  getNodeForm(def_n_item);
				 if(nForm!=null){
					 ins_n_p.setFORM_CODE(nForm.getFORM_CODE());  
					 ins_n_p.setFORM_TYPE(nForm.getFORM_TYPE());
				 }   
				 ins_n_p.setHANDLE_IDS(getHandlerIds(def_n_item));
				 ins_n_p.setBO_ID(bo_id);
				 ins_n_p.setBO_STATUS(bo_STATUS);
				 if(accepterIds!=null&&accepterIds.length==1){
					 ins_n_p.setACTOR_ID(accepterIds[0]);
				 }
				 ins_n_p.setP_I_NID(beforeInsNode.getID()); 
				 getJpaDao().save(ins_n_p);
				 
				 retTasks.add(ins_n_p);
			}
		}  
		 
		return retTasks;
	} 
	

	@Override
	public void DO_TASK_SUBMIT(String taskId, String opid, Date optime,
			String bo_id, int bo_STATUS, 
			String next_bo_id, int next_bo_STATUS,
			String approveResult,
			String approveMemo, String... accepterIds) {
		TB_WFM_INS_NODE ins_n = getJpaDao().find(TB_WFM_INS_NODE.class, taskId);
		TB_WFM_INS_WORKFLOW ins_wf = getJpaDao().find(TB_WFM_INS_WORKFLOW.class, ins_n.getWFID());  
		if(bo_id!=null && !bo_id.isEmpty()){
			ins_n.setBO_ID(bo_id);
			ins_n.setBO_STATUS(bo_STATUS);
		}
		ins_n.setACTOR_ID(opid);
		ins_n.setEND_TIME(optime); 
		ins_n.setPROCESS_RESULT(approveResult);
		ins_n.setPROCESS_INFO(approveMemo);
		ins_n.setN_SN(ins_wf.getPROC_RESULT()); 
		 
		if(ins_n.getBO_ID()==null || ins_n.getBO_ID().isEmpty()){
			throw new UserException("工作未处理，不能提交！");
		}
		
	    getJpaDao().update(ins_n); 
	    
        try { 
			startTask(opid,next_bo_id,next_bo_STATUS,optime,ins_n,ins_n.getNID(),approveResult,accepterIds);
			ins_wf.setPROC_RESULT(ins_wf.getPROC_RESULT()+1);  
		} catch (WorkFlowException e) {
			if(e.getRet() == WorkFlowException.RET_END){
				ins_wf.setEND_TIME(optime); 
			}
		}  
	    
	    getJpaDao().update(ins_wf);
	}

	@Override
	public String DO_START_PROCESS(String wfCode, Integer wfVersion,
			String opid, Date optime, String bo_id, int bo_STATUS,
			String approveResult, String approveMemo) { 
		HashMap param=new HashMap();
		param.put("CODE", wfCode);
		param.put("VERSION", wfVersion);
		
		TB_WFM_DEF_WORKFLOW def_wf = ObjectUtils.mapToJavaBean((Map) querySingleResult("Q_WFM_DEF_WORKFLOW.GET_TB_WFM_DEF_WORKFLOW_BY_CODE_VERSION",param ),TB_WFM_DEF_WORKFLOW.class);
		 
		TB_WFM_INS_WORKFLOW ins_wf = new TB_WFM_INS_WORKFLOW();
		ObjectUtils.copyJavaBeanToBean(def_wf, ins_wf, "ID");
		ins_wf.setDEF_ID(def_wf.getID());
		ins_wf.setSTART_TIME(optime);
		ins_wf.setID(ins_wf.uuid());
		ins_wf.setPROC_RESULT(1);
	    getJpaDao().save(ins_wf);
	 
		param=new HashMap();
		param.put("BO_CODE", null);
		param.put("WFID", def_wf.getID());
		TB_WFM_DEF_NODE def_n = (TB_WFM_DEF_NODE) querySingleResult("Q_WFM_DEF_WORKFLOW.GET_TB_WFM_DEF_NODE_BY_BOCODE_WFID",param); 
			
		TB_WFM_INS_NODE ins_n = new TB_WFM_INS_NODE();
		ins_n.setBO_ID(bo_id);
		ins_n.setBO_STATUS(bo_STATUS);
		ins_n.setBO_OP_ITEM(optime);
		ins_n.setCREATE_TIME(optime);
		ins_n.setCREATERID(opid);
		ins_n.setACTOR_ID(opid);
		
		ins_n.setID(ins_n.uuid());
		ins_n.setWFID(ins_wf.getID());
		ins_n.setN_SN(1);
		ins_n.setNID(def_n.getID());
		ins_n.setN_NAME(def_n.getNAME()); 
		ins_n.setN_CODE(def_n.getCODE());
		ins_n.setN_TYPE(def_n.getTYPE());
		TB_WFM_DEF_NODEFORM nForm =  getNodeForm(def_n);
		if(nForm!=null){
			 ins_n.setFORM_CODE(nForm.getFORM_CODE());  
			 ins_n.setFORM_TYPE(nForm.getFORM_TYPE());
		}   
		ins_n.setPROCESS_RESULT(approveResult);
		ins_n.setPROCESS_INFO(approveMemo);  
		
		List<TB_WFM_INS_NODE> retTasks=null;;
		 
		try {
			retTasks = startTask(opid,bo_id,bo_STATUS,optime,ins_n,ins_n.getNID(),approveResult);
		} catch (WorkFlowException e) { 
			e.printStackTrace();
		}
		if(retTasks!=null&&retTasks.size()>0){
			ins_n.setEND_TIME(optime);
		}

		getJpaDao().save(ins_n);
		
		return ins_wf.getID();
	}

	@Override
	public void DO_TASK_SUBMIT(String taskId, String opid, Date optime,
			String approveResult, String approveMemo, String... accepterIds) {
		DO_TASK_SUBMIT(  taskId,   opid,   optime, null, 0,  null, 0, approveResult, approveMemo,  accepterIds); 
	}

	@Override
	public void SAVE_TASK_BO(String taskId,String bo_id,int bo_STATUS,String opid,Date optime,String approveMemo) {
		TB_WFM_INS_NODE ins_n = getJpaDao().find(TB_WFM_INS_NODE.class, taskId);
		if(ins_n!=null){
			//处理人不为空，且不是自己处理的任务，不能保存
			if(ins_n.getACTOR_ID()!=null&&!ins_n.getACTOR_ID().isEmpty()&&!ins_n.getACTOR_ID().equals(opid)){
				if(ins_n.getEND_TIME()!=null){
					throw new UserException("此任务已被其他人处理完毕！");
				}else{
					throw new UserException("此任务其他人在处理中！");
				} 
			}else{
				ins_n.setACTOR_ID(opid);
				ins_n.setBO_ID(bo_id);
				ins_n.setBO_STATUS(bo_STATUS);
				ins_n.setBO_OP_ITEM(optime);
				ins_n.setPROCESS_INFO(approveMemo);
				getJpaDao().update(ins_n);
			} 
		} else{
			throw new ServiceException("任务找不到，任务ID="+taskId);
			
		}
	}
 
 
 
}

class WorkFlowException extends Exception{ 
	private static final long serialVersionUID = 1L;
	public static final int RET_END=1;
	
	private int ret;
	public WorkFlowException(int ret){
		this.ret = ret;
	}
	public int getRet() {
		return ret;
	}
	public void setRet(int ret) {
		this.ret = ret;
	}
	
}
